package com.jeesite.modules.dp.web;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpServletRequest;

import com.jeesite.common.codec.DesUtils;
import com.jeesite.common.lang.DateUtils;
import com.jeesite.modules.dp.service.user.ExtendUserService;
import com.jeesite.modules.stock.service.UserStocksService;
import com.jeesite.modules.utils.NVL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.jeesite.common.config.Global;
import com.jeesite.common.entity.Extend;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.msg.SmsUtils;
import com.jeesite.common.service.ServiceException;
import com.jeesite.common.web.BaseController;
import com.jeesite.modules.dp.service.yqrecord.DpYqrecordService;
import com.jeesite.modules.sys.entity.EmpUser;
import com.jeesite.modules.sys.entity.Employee;
import com.jeesite.modules.sys.entity.Office;
import com.jeesite.modules.sys.entity.User;
import com.jeesite.modules.sys.service.EmpUserService;
import com.jeesite.modules.sys.service.UserService;
import com.jeesite.modules.sys.utils.UserUtils;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

@Controller
@Api(tags = "DPAccount - 账号服务")
@RequestMapping(value = "/dpaccount")
@ConditionalOnProperty(name = {"user.enabled", "web.core.enabled"}, havingValue = "true", matchIfMissing = true)
public class DpAccountController extends BaseController {

    @Autowired
    private UserService userService;
    @Autowired
    private EmpUserService empUserService;
    @Autowired
    private DpYqrecordService dpYqrecordService;
    @Autowired
    private ExtendUserService extendUserService;

    @Value("${sms-config.register-temid}")
    private String registerSmsTmpId;

    @Value("${sms-config.upwd-temid}")
    private String upwdSmsTmpId;

    @Value("${sms-config.access-key}")
    private String accessKey;

    @Value("${sms-config.access-key-secret}")
    private String accessKeySecret;

    private static final ConcurrentHashMap<String, Object> USER_CACHE = new ConcurrentHashMap<>();

    private final Logger log = LoggerFactory.getLogger(DpAccountController.class);


    @RequestMapping(value = "getSmscodeAliYun")
    @ResponseBody
    @ApiOperation(value = "获取登录的短信或邮件验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "验证码类型", required = true, paramType = "query", type = "String"),
            @ApiImplicitParam(name = "telnum", value = "手机号", required = true, paramType = "query", type = "String")})
    public String getSmscodeAliYun(String type, String telnum, HttpServletRequest request) {
        // 如果是注册，判断是否注册
        if ("reg".equals(type)) {
            if (extendUserService.getUserByLoginCode(telnum) != null) {
                return renderResult(Global.FALSE, text("该号码已经注册或使用"));
            }
        } else {
            if (extendUserService.getUserByLoginCode(telnum) == null) {
                return renderResult(Global.FALSE, text("该手机号未注册账号"));
            }
        }
        // 如果是更新，判断是否注册
        return getValidCodeNew(type, telnum, request);
    }

    private String getValidCodeNew(String type, String telnum, HttpServletRequest request) {
        // 校验图片验证码，防止重复机器人。

        // 操作是否频繁验证， 如果离上次获取验证码小于20秒，则提示操作频繁。
        Date date = UserUtils.getCache(type + telnum + "LastDate");
        if (date != null && (System.currentTimeMillis() - date.getTime()) / (1000L) < 20L) {
            return renderResult(Global.FALSE, text("您当前操作太频繁，请稍等一会再操作！"));
        }
        // 生成验证码，并缓存。
        String verifyCode = StringUtils.getRandomNum(6);
        USER_CACHE.put(String.join("_", type, telnum, "VerifyCode"), verifyCode);
        USER_CACHE.put(String.join("_", type, telnum, "LastDate"), System.currentTimeMillis());
        String smsTempId = switch (type) {
            case "reg" -> registerSmsTmpId;
            case "upwd" -> upwdSmsTmpId;
            default -> null;
        };
        // 发送邮箱或短信验证码
        return sendSmsValidCodeNew(smsTempId, telnum, verifyCode);

    }

    // 模版CODE】SMS_476910682 SMS_476870683
    private String sendSmsValidCodeNew(String tmpid, String account, String code) {
        if (tmpid == null) {
            return renderResult(Global.FALSE, text("系统出现了点问题，错误信息：{0}", "短信发送模板为空"));
        }
        try {
            Map<String, String> configs = new HashMap<>();
            configs.put("accessKey", accessKey);
            configs.put("accessKeySecret", accessKeySecret);
            SmsUtils.send(tmpid, code, account, configs);
        } catch (Exception e) {
            return renderResult(Global.FALSE, text("系统出现了点问题，错误信息：{0}", e.getMessage()));
        }
        return renderResult(Global.TRUE, text("验证码已发送到“{0}”的手机号码，请尽快查收！", account));
    }

    @PostMapping(value = "saveRegByValidCodeNew")
    @ResponseBody
    @ApiOperation(value = "根据短信或邮件验证码注册用户")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "logincode", value = "登录账号", required = true, paramType = "query", type = "String"),
            @ApiImplicitParam(name = "password", value = "登录密码", required = true, paramType = "query", type = "String"),
            @ApiImplicitParam(name = "regValidCode", value = "手机或邮箱接受的验证码", required = true),})
    public String saveRegByValidCodeNew(String loginCode, String password, String regValidCode, String yqm,
                                        HttpServletRequest request) {
        if (!"true".equals(Global.getConfig("sys.account.registerUser"))) {
            return renderResult(Global.FALSE, text("当前系统没有开启注册功能！"));
        }

        if (StringUtils.isBlank(loginCode) || StringUtils.isBlank(regValidCode)) {
            return renderResult(Global.FALSE, text("手机号或验证码不能为空!"));
        }
        if (StringUtils.isBlank(password)) {
            return renderResult(Global.FALSE, text("密码不能为空!"));
        }
        // 判断帐号是否存在
        User user = extendUserService.getUserByLoginCode(loginCode);
        if (user != null) {
            return renderResult(Global.FALSE, "账号已存在");
        }

        String corpCode = UserUtils.getCache("regCorpCode");
        String corpName = UserUtils.getCache("regCorpName");
        String email = NVL.nvl(UserUtils.getCache("regEmail"), "");

        String verifyCode = (String) USER_CACHE.get(String.join("_", "reg", loginCode, "VerifyCode"));
        Long verifyCodeSendTime = (Long) USER_CACHE.get(String.join("_", "reg", loginCode, "LastDate"));

        // 新增设置用户名为用户手机号后4位+随机数,暂不验证，注销掉，需放开
        if (verifyCode == null || verifyCodeSendTime == null || !verifyCode.equals(regValidCode)) {
            return renderResult(Global.FALSE, text("验证码错误，请重新输入验证码！"));
        }
        long now = System.currentTimeMillis();
        // 验证码是否超时
        int validTime = Integer.parseInt(Global.getConfig("sys.account.validCodeTimeout", "1")); // 验证码有效时间（单位分钟，0表示不限制，默认值10）
        if ((now - verifyCodeSendTime) / 1000 / 60 > validTime) {
            return renderResult(Global.FALSE, text("验证码已过期, 请重新获取验证码！"));
        }

        // 新增并保存用户。
        EmpUser u = new EmpUser();
        u.setLoginCode(loginCode);
        u.setCorpCode_(NVL.nvl(corpCode, null));
        u.setCorpName_(NVL.nvl(corpName, null));
        u.setEmail(email);
        u.setMobile(loginCode);
        u.setUserType("employee");
        u.setMgrType(User.MGR_TYPE_NOT_ADMIN);
        u.setStatus(User.STATUS_NORMAL); // 正常状态
        u.setUserName("用户" + loginCode.substring(7) + "_" + StringUtils.getRandomNum(4));
        u.setPassword(password);

        // 邀请码设置，会员日期设置
        Extend uex = new Extend();
        uex.setExtendS1(loginCode.substring(7) + StringUtils.getRandomStr(15));
        uex.setExtendF1(0.00);
        u.setExtend(uex);

        Employee oe = new Employee();
        Office office = new Office();
        office.setOfficeCode("SD002");
        office.setOfficeName("外部用户");
        oe.setOffice(office);
        u.setEmployee(oe);
        u.setUserRoleString("user");

        empUserService.save(u);
        userService.saveAuthRole(u);

        // 查询邀请码的用户，并生成邀请记录，同时余额+1
        User yqmUser = null;
        if (!StringUtils.isEmpty(yqm)) {
            // 查询邀请码所属用户
            yqmUser = dpYqrecordService.getUserByYqm(yqm);
        }
        dpYqrecordService.saveRegUser(u, yqmUser);
        // 要设置部门，设置角色,邀请码操作等

        // 注册用户后，清理缓存
        UserUtils.removeCache("reg" + loginCode + "ValidCode");
        UserUtils.removeCache("reg" + loginCode + "LastDate");

        USER_CACHE.remove(String.join("_", "reg", loginCode, "VerifyCode"));
        USER_CACHE.remove(String.join("_", "reg", loginCode, "LastDate"));

        return renderResult(Global.TRUE, text("恭喜你，您的账号 {0} 注册成功！", u.getLoginCode()));
    }

    @PostMapping(value = "savePwdByValidCodeNew")
    @ResponseBody
    @ApiOperation(value = "根据短信或邮件验证码重置密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "loginCode", value = "登录账号", required = true, paramType = "query", type = "String"),
            @ApiImplicitParam(name = "upwdValidCode", value = "手机或邮箱接受的验证码", required = true),
            @ApiImplicitParam(name = "password", value = "新密码", required = true, paramType = "query", type = "String"),})
    public String savePwdByValidCodeNew(User user, String upwdValidCode, HttpServletRequest request) {

        User uuu = userService.getByLoginCode(user);
        if (uuu == null) {
            return renderResult(Global.FALSE, "手机号账号不存在");
        }

        boolean isTimeout = true;
        String validTime = Global.getConfig("sys.account.validCodeTimeout", "10"); // 验证码有效时间（单位分钟，0表示不限制，默认值10）

        String validCode = UserUtils.getCache("upwd" + user.getLoginCode() + "ValidCode");
        Date date = (Date) UserUtils.getCache("upwd" + user.getLoginCode() + "LastDate");

        if ("0".equals(validTime) || (date != null
                && (System.currentTimeMillis() - date.getTime()) / (1000L) < 60 * Long.parseLong(validTime))) {
            isTimeout = false;
        }

        // 新增设置用户名为用户手机号后4位+随机数,暂不验证，注销掉，需放开
        if (!(validCode != null && validCode.equals(upwdValidCode) && !isTimeout)) {
            return renderResult(Global.FALSE, text("验证码不正确或已失效，请重新获取验证码！"));
        }

        try {
            userService.updatePassword(uuu.getUserCode(), user.getPassword());
            // 清除缓存
            UserUtils.removeCache("upwd" + user.getLoginCode() + "ValidCode");
            UserUtils.removeCache("upwd" + user.getLoginCode() + "LastDate");
        } catch (ServiceException se) {
            return renderResult(Global.FALSE, se.getMessage());
        }
        return renderResult(Global.TRUE, text("恭喜你，您的账号 {0} 密码找回成功！", user.getLoginCode()));
    }

}
